<template>
  <div class="travel_price">
    <div class="base_details_title">基本信息</div>
    <div class="base_details_content_second">
      <el-form
        ref="baseDataFormRef"
        :model="baseData"
        :rules="rules"
        label-width="120px"
        :disabled="readOnly"
        class="base_details_form"
      >
        <el-row>
          <el-col :span="8">
            <el-form-item label="套餐名称" prop="name">
              <el-input v-model="baseData.name" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="套餐天数" prop="packageDayNum">
              <el-input
                v-model="baseData.packageDayNum"
                type="number"
                onkeyup="value=value.replace(/^[^\d]+/g,'')"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="住宿天数" prop="packageNightNum">
              <el-input
                v-model="baseData.packageNightNum"
                type="number"
                onkeyup="value=value.replace(/^[^\d]+/g,'')"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </div>
    <div class="base_details_title">日期价格设置</div>
    <div class="base_details_content_second">
      <TravelPriceOperate
        ref="priceOperateRef"
        @execute="execute"
        @checkOperateChange="checkOperateChange"
        @calendarSwitch="calendarSwitch"
      />
      <PriceCalendar
        ref="calendarRef"
        :number="calendarNumber"
        @select="calendarSelect"
        @del="calendarDel"
      />
      <div id="scrollPoint"></div>
      <el-table-v2
        ref="tableRef"
        :columns="travelPriceColumns"
        :data="travelPriceDate"
        :width="980"
        :height="700"
      >
        <template #row="props">
          <Row v-bind="props" />
        </template>
        <template #empty> </template>
      </el-table-v2>
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, nextTick, cloneVNode, defineExpose } from "vue";
import TravelPriceOperate from "./TravelPriceOperate.vue";
import PriceCalendar from "./PriceCalendar.vue";
import msg from "@ui/message";

const readOnly = ref(false);
const tableRef = ref(null);
const baseDataFormRef = ref(null);
const baseData = reactive({
  id: null,
  packageCode: null,
  name: "",
  packageDayNum: "",
  packageNightNum: "",
  // groupPeopleNum: "",
  // expectPeopleNum: "",
  // packagePeopleNum: "",
  // stockNum: "",
  // orderPeopleNum: "",
});

const calendarNumber = ref(localStorage.getItem("calendarNumber") || 6);
const rules = {
  name: [
    {
      required: true,
      message: "请输入套餐名称",
      trigger: "blur",
    },
  ],
  packageDayNum: [
    {
      required: true,
      message: "请输入套餐天数",
      trigger: "blur",
    },
  ],
  packageNightNum: [
    {
      required: true,
      message: "请输入住宿天数",
      trigger: "blur",
    },
  ],
};

const priceOperateRef = ref(null);
const calendarRef = ref(null);
var travelPriceDate = ref([]);

const travelPriceColumns = [
  {
    key: "priceDate",
    dataKey: "priceDate",
    title: "日期",
    width: 120,
  },
  {
    key: "priceType",
    dataKey: "priceType",
    title: "价格类型",
    width: 130,
  },
  {
    key: "withBedFlag",
    dataKey: "withBedFlag",
    title: "是否占床",
    width: 100,
    cellRenderer: (data) => (
      <el-switch
        v-model={data.rowData.withBedFlag}
        inline-prompt
        active-text="占床"
        inactive-text="不占"
        active-value={1}
        inactive-value={0}
        size="large"
      />
    ),
  },
  {
    key: "competitorPrice",
    dataKey: "competitorPrice",
    title: "同行价",
    width: 100,
    cellRenderer: (data) => (
      <el-input type="number" v-model={data.rowData.competitorPrice} />
    ),
  },
  {
    key: "sellPrice",
    dataKey: "sellPrice",
    title: "销售价",
    width: 100,
    cellRenderer: (data) => (
      <el-input type="number" v-model={data.rowData.sellPrice} />
    ),
  },
  {
    key: "markingPrice",
    dataKey: "markingPrice",
    title: "划线价",
    width: 100,
    cellRenderer: (data) => (
      <el-input type="number" v-model={data.rowData.markingPrice} />
    ),
  },
  {
    key: "singleRoomPrice",
    dataKey: "singleRoomPrice",
    title: "单房差",
    width: 100,
    cellRenderer: (data) => (
      <el-input
        type="number"
        v-model={data.rowData.singleRoomPrice}
        onchange={syncDataChange.bind(
          this,
          data.rowData,
          data.rowIndex,
          "singleRoomPrice",
          false
        )}
      />
    ),
  },
  {
    key: "groupPeopleNum",
    dataKey: "groupPeopleNum",
    title: "最低成",
    width: 90,
    cellRenderer: (data) => (
      <el-input
        type="number"
        v-model={data.rowData.groupPeopleNum}
        onchange={syncDataChange.bind(
          this,
          data.rowData,
          data.rowIndex,
          "groupPeopleNum",
          true
        )}
      />
    ),
  },
  {
    key: "expectPeopleNum",
    dataKey: "expectPeopleNum",
    title: "预收位",
    width: 90,
    cellRenderer: (data) => (
      <el-input
        type="number"
        v-model={data.rowData.expectPeopleNum}
        onchange={syncDataChange.bind(
          this,
          data.rowData,
          data.rowIndex,
          "expectPeopleNum",
          true
        )}
      />
    ),
  },
  {
    key: "packagePeopleNum",
    dataKey: "packagePeopleNum",
    title: "最低预",
    width: 90,
    cellRenderer: (data) => (
      <el-input
        type="number"
        v-model={data.rowData.packagePeopleNum}
        onchange={syncDataChange.bind(
          this,
          data.rowData,
          data.rowIndex,
          "packagePeopleNum",
          true
        )}
      />
    ),
  },
  {
    key: "orderPeopleNum",
    dataKey: "orderPeopleNum",
    title: "最大预",
    width: 90,
    cellRenderer: (data) => (
      <el-input
        type="number"
        v-model={data.rowData.orderPeopleNum}
        onchange={syncDataChange.bind(
          this,
          data.rowData,
          data.rowIndex,
          "orderPeopleNum",
          true
        )}
      />
    ),
  },
  {
    key: "stockNum",
    dataKey: "stockNum",
    title: "库存",
    width: 80,
    cellRenderer: (data) => (
      <el-input
        type="number"
        v-model={data.rowData.stockNum}
        onchange={syncDataChange.bind(
          this,
          data.rowData,
          data.rowIndex,
          "stockNum",
          true
        )}
      />
    ),
  },
  {
    key: "del",
    dataKey: "del",
    title: "操作",
    width: 80,
    cellRenderer: (data) => (
      <el-button
        type="danger"
        icon="Delete"
        onClick={priceDelete.bind(this, data.rowData, data.rowIndex)}
      />
    ),
  },
];

function syncDataChange(data, index, key, checkNull) {
  if (checkNull) {
    for (const chackBaseKey of priceOperateRef.value.chackBaseKey) {
      if (data[chackBaseKey] == null || data[chackBaseKey].length == 0) {
        data[key] = null;
        return;
      }
    }
  }

  for (let i = index + 1; i < index + data.spacsLength; i++) {
    const element = travelPriceDate.value[i];
    element[key] = data[key];
  }
}
function calendarSwitch(val) {
  if (val) {
    calendarNumber.value = 6;
    localStorage.setItem("calendarNumber", 6);
  } else {
    calendarNumber.value = 12;
    localStorage.setItem("calendarNumber", 12);
  }
  loadCalendar();
}

function formatDate(date) {
  return (
    date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate()
  );
}

function insertTemplate(date, source, template) {
  for (let index = 0; index < template.price.length; index++) {
    const element = template.price[index];
    let data = {
      priceDate: formatDate(date),
      dateSrc: date,
      spacsIndex: index,
      spacsLength: template.price.length,
    };
    if (template.other != null) {
      for (const key in template.other) {
        data[key] = template.other[key];
      }
    }
    for (const key in element) {
      if (!(key in data)) {
        data[key] = element[key];
      }
    }
    source.push(data);
  }
}

/**
 *  添加日期价格
 * 1、检查与原数据日期是否冲突
 * 2、添加数据
 * 3、排序
 */
function addTravelDate(isDuringCheck, startDate, endDate, week, templateData) {
  if (isDuringCheck) {
    //判断新增日期是否和已编辑日期冲突
    if (isDuringDate(startDate, endDate, week)) {
      msg.error("添加日期价格于现有日期价格冲突");
      return false;
    }
  }

  var prevDate = startDate;
  var dateData = [];

  if (isMeetWeek(startDate, week)) {
    insertTemplate(startDate, dateData, templateData);
  }

  //构建日期区间
  const day = diffDay(startDate, endDate);
  for (let index = 0; index < day; index++) {
    prevDate = nextDay(prevDate);
    if (isMeetWeek(prevDate, week)) {
      insertTemplate(prevDate, dateData, templateData);
    }
  }

  //日期合并
  if (travelPriceDate.value.length <= 0) {
    travelPriceDate.value = travelPriceDate.value.concat(dateData);
  } else {
    travelPriceDate.value = travelPriceDate.value.concat(dateData);
    //排序
    travelPriceDate.value.sort((a, b) => {
      return a.dateSrc - b.dateSrc;
    });
  }
  return true;
}

/**
 * 覆盖日期价格
 * 1、原数据中删除需要覆盖的日期
 * 2、添加数据
 * 3、排序
 */
function coverTravelDate(startDate, endDate, week, templateData) {
  for (var i = travelPriceDate.value.length - 1; i >= 0; i--) {
    let oldDate = travelPriceDate.value[i];
    if (
      isMeetWeek(oldDate.dateSrc, week) &&
      oldDate.dateSrc >= startDate &&
      oldDate.dateSrc <= endDate
    ) {
      travelPriceDate.value.splice(i, 1);
    }
  }
  addTravelDate(false, startDate, endDate, week, templateData);
}

function loadCalendar() {
  nextTick(() => {
    calendarRef.value.setChecked(travelPriceDate.value);
  });
}

function isMeetWeek(date, week) {
  return week.includes(date.getDay());
}

function isDuringDate(startDate, endDate, week) {
  for (const oldDate of travelPriceDate.value) {
    if (!isMeetWeek(oldDate.dateSrc, week)) {
      continue;
    }
    if (oldDate.dateSrc >= startDate && oldDate.dateSrc <= endDate) {
      return true;
    }
  }
  return false;
}

function diffDay(date_1, date_2) {
  let totalDays, diffDate;
  diffDate = Math.abs(date_1 - date_2);
  totalDays = Math.floor(diffDate / (1000 * 3600 * 24));
  return totalDays;
}

function nextDay(date) {
  date = new Date(date);
  date = +date + 1000 * 60 * 60 * 24;
  date = new Date(date);
  return date;
}

function priceDelete(date, index) {
  travelPriceDate.value.splice(index, date.spacsLength);
  calendarRef.value.setChecked(travelPriceDate.value);
}

function checkOperateChange(callback) {
  if (travelPriceDate.value.length <= 0) {
    return callback(true);
  } else {
    return callback(false);
  }
}

const Row = (element) => {
  const { rowData, rowIndex, cells } = element;
  if (rowData.spacsLength > 1 && rowData.spacsIndex == 0) {
    const cellDate = cells[0];
    cells[0] = cloneVNode(cellDate, {
      style: {
        ...cellDate.props.style,
        backgroundColor: "#fff",
        borderRightStyle: "solid",
        borderRightWidth: "1px",
        color: "#409eff",
        borderRightColor: "var(--el-table-border-color)",
        height: `${rowData.spacsLength * 50 - 1}px`,
        alignSelf: "flex-start",
        zIndex: 1,
      },
    });
    for (let index = 5; index <= 11; index++) {
      const cellDel = cells[index];
      cells[index] = cloneVNode(cellDel, {
        style: {
          ...cellDel.props.style,
          backgroundColor: "#fff",
          borderLeftStyle: "solid",
          borderLeftWidth: "1px",
          borderLeftColor: "var(--el-table-border-color)",
          height: `${rowData.spacsLength * 50 - 1}px`,
          alignSelf: "flex-start",
          zIndex: 1,
        },
      });
    }
  }

  return cells;
};

function calendarDel(data) {
  for (let index = 0; index < travelPriceDate.value.length; index++) {
    const element = travelPriceDate.value[index];
    if (
      data.year == element.dateSrc.getFullYear() &&
      data.month == element.dateSrc.getMonth() + 1 &&
      data.day == element.dateSrc.getDate()
    ) {
      travelPriceDate.value.splice(index, element.spacsLength);
      break;
    }
  }
}

function calendarSelect(data, callback) {
  const date = new Date(data.year, data.month - 1, data.day);
  if (data.checked) {
    document.getElementById("scrollPoint").scrollIntoView();
    jumpTableDate(date);
    callback(false);
  } else {
    if (priceOperateRef.value.validate()) {
      callback(insertTableDate(date));
    } else {
      callback(false);
    }
  }
}

function jumpTableDate(date) {
  for (let index = 0; index < travelPriceDate.value.length; index++) {
    const element = travelPriceDate.value[index];
    if (
      date.getFullYear() == element.dateSrc.getFullYear() &&
      date.getMonth() == element.dateSrc.getMonth() &&
      date.getDate() == element.dateSrc.getDate()
    ) {
      tableRef.value.scrollToRow(index, "start");
      break;
    }
  }
}

function insertTableDate(date) {
  const template = priceOperateRef.value.getOperate().template;
  var isExist = false;
  for (const price of travelPriceDate.value) {
    if (
      date.getFullYear() == price.dateSrc.getFullYear() &&
      date.getMonth() == price.dateSrc.getMonth() &&
      date.getDate() == price.dateSrc.getDate()
    ) {
      isExist = true;
    }
  }
  if (!isExist) {
    insertTemplate(date, travelPriceDate.value, template);
    travelPriceDate.value.sort((a, b) => {
      return a.dateSrc - b.dateSrc;
    });
    return true;
  }
  return false;
}

function execute(data) {
  if (data.operate == "clear") {
    travelPriceDate.value = [];
    loadCalendar();
  } else if (data.operate == "modify") {
    let startDate = new Date(data.date[0]);
    let endDate = new Date(data.date[1]);
    coverTravelDate(startDate, endDate, data.week, data.template);
    loadCalendar();
  } else if (data.operate == "add") {
    let startDate = new Date(data.date[0]);
    let endDate = new Date(data.date[1]);
    if (addTravelDate(true, startDate, endDate, data.week, data.template)) {
      loadCalendar();
    }
  }
}

function improtTravelDate(data, template) {
  const nowDate = new Date(new Date().setHours(0, 0, 0, 0));
  var index = 0;
  var travelData = [];
  for (const e of data) {
    var handleData = {};
    handleData.dateSrc = new Date(e.priceDate);
    if (handleData.dateSrc < nowDate) {
      continue;
    }
    for (const key in e) {
      if (key != "dateSrc") {
        handleData[key] = e[key];
      }
    }
    handleData.spacsIndex = index % template.price.length;
    handleData.spacsLength = template.price.length;
    index++;
    travelData.push(handleData);
  }
  travelPriceDate.value = travelData;
}

function improtData(data) {
  baseData.id = data.id;
  baseData.packageCode = data.packageCode;
  baseData.name = data.name;
  baseData.packageDayNum = data.packageDayNum;
  baseData.packageNightNum = data.packageNightNum;
  // baseData.groupPeopleNum = data.groupPeopleNum;
  // baseData.expectPeopleNum = data.expectPeopleNum;
  // baseData.packagePeopleNum = data.packagePeopleNum;
  // baseData.stockNum = data.stockNum;
  // baseData.orderPeopleNum = data.orderPeopleNum;

  priceOperateRef.value.importData({ price: data.packagePriceItems });
  improtTravelDate(data.packagePriceDateItems, {
    price: data.packagePriceItems,
  });
  loadCalendar();
}

function reset() {
  baseDataFormRef.value.resetFields();
  priceOperateRef.value.resetData();
  travelPriceDate.value = [];
  loadCalendar();
}

function save(callback) {
  baseDataFormRef.value.validate((valid) => {
    if (valid) {
      if (travelPriceDate.value.length > 0) {
        var data = {};

        for (const key in baseData) {
          data[key] = baseData[key];
        }
        let operateData = priceOperateRef.value.getData();
        data.packagePriceItems = operateData.price;
        data.packagePriceDateItems = travelPriceDate.value;
        callback(data);
      } else {
        callback(false);
        msg.error("请设置日期价格");
      }
    } else {
      callback(false);
    }
  });
}
function clear() {
  baseData.id = null;
}
defineExpose({ improtData, reset, save, clear });
</script>

<style lang="scss" scoped>
.travel_price {
  .base_details_title {
    margin: 5px 0;
  }

  .base_details_content_second {
    margin-bottom: 0;
  }
}
</style>